/*  

Cafechess Library: Cover basic chess programming needs, like GUI, Engine integration, 
FEN and PGN parsing.

                 \\|//
                 (o o)
--------------ooO-(_)-Ooo----------------------------------
Copyright (C) 2009  By Gregory A. Prentice Snoqualmie, WA
                    www.cafechess.org
                    cafechess@comcast.net
                      Oooo
--------------oooO----(  )---------------------------------
              (  )    (_/
               \_)

Microsoft Public License (Ms-PL)
               
Revisions:

Author        Date    Description:

*/
using System;
using System.Threading;

namespace Cafechess.Threading
{
	/// <summary>
	/// Abstract semaphore class definition.  Provides methods and interfaces to implement
	/// counting, bounded-counting, and regular aquire / release semaphores.
	/// </summary>
	public abstract class AbstractSemaphore
	{
    /// <summary>
    /// Default constructor - callable only by derived classes.  Initializes the class members.
    /// </summary>
    /// 
    /// <param name="nMinCount">The required acquisition count before a call to <code>Release()</code> signals.</param>
    /// <param name="nMaxCount">The required acquisition count before a call to <code>Aquire()</code> blocks.</param>
    protected AbstractSemaphore( int nMinCount, int nMaxCount )
    {
      cnCount = 0;
      cnMinCount = nMinCount;
      cnMaxCount = nMaxCount;
    }

    /// <summary>
    /// Acquire the semaphore and block if the acquisition count is larger
    /// than a threshold value.  Increments the aquisition count each time
    /// the function is called.
    /// </summary>
    public void Acquire()
    {
      lock( this )
      {
        if( cnCount >= cnMaxCount )
        {
          Monitor.Wait( this );
        }

        ++cnCount;
      }
    }

    /// <summary>
    /// Release the semaphore and signal a blocked thread if the acquisition
    /// count is less than a threshold value.  Decrements the aquisition count
    /// each time the function is called.
    /// </summary>
    public void Release()
    {
      lock( this )
      {
        if( cnCount <= cnMinCount )
        {
          Monitor.Pulse( this );
        }

        --cnCount;
      }
    }

    /// <summary>
    /// Resets the semaphore to its initial state.  User defined implementation.
    /// </summary>
    public abstract void Reset();
    

    protected int cnCount;              // Stores the semaphore aquisition count (calls to P() - calls to V()).
    protected readonly int cnMinCount;  // Stores the required acquisition count before a call to V() signals.
    protected readonly int cnMaxCount;  // Stores the required acquisition count before a call to P() blocks.
	}
}
